package com.jiao.service.impl;

import com.jiao.constants.Constants;
import com.jiao.domain.Result;
import com.jiao.domain.VO.CategorVo;
import com.jiao.domain.entity.ArticleCategory;
import com.jiao.domain.entity.Category;
import com.jiao.mapper.ArticleCategoryMapper;
import com.jiao.mapper.CategoryMapper;
import com.jiao.service.CategoryService;
import com.jiao.utils.BeanCopyUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/*
* 1，练习了stream流的项目实际使用（List，Map，Set）
* 2，理解 Vo，DTO的对象分类，和对象拷贝的注意事项和实际使用。
* 3，Mybatis-plus对mapper层，service层，page分页的封装Api的使用与理解。
* */
@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category>  implements CategoryService  {
    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    ArticleCategoryMapper articleCategoryMapper;

    @Override
    public Result<List<CategorVo>> getCategoryList() {
        // 1，先取正常的对应关系表数据。然后将分类的id去重
        LambdaQueryWrapper<ArticleCategory> queryWrapper = new LambdaQueryWrapper<>();
        // 查找所有的数据。
        List<ArticleCategory> articleCategories = articleCategoryMapper.selectList(queryWrapper);
        Set<Long> ids = articleCategories.stream().map(ArticleCategory::getArticleId).collect(Collectors.toSet());
        // 2，然后根据分类id，去取分类表的数据。
        List<Category> categories = listByIds(ids);
        categories= categories.stream().filter(category -> Constants.ARTICLE_STATUS_NORMAL.equals(category.getStatus()))
                .collect(Collectors.toList());
        // 3，进行拷贝对象返回
        List<CategorVo> categorVoList = BeanCopyUtils.copyBeanList(categories,CategorVo.class);
        return Result.success(categorVoList);
    }

    /*
    * 页面上需要展示分类列表，用户可以点击具体的分类查看该分类下的文章列表。
    * 条件：
    * 1，要求只展示有发布正式文章的分类。查中间表有数据的，
    * 2，必须是正常状态的分类
    * 取出的结果：有它所包含的文章id数组。
    *
    * 因为这里面都是select,所以不需要加事务管理注解。
    * */
    @Override
    public Result<List<CategorVo>> getCategoryList2() {

        // 1，取是正常分类的分类数据
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getStatus, Constants.ARTICLE_STATUS_NORMAL);//正常分类
        List<Category> categories = categoryMapper.selectList(queryWrapper);
        // 2，取出分类ID数组
        List<Long> CategoryIds = categories.stream().map(Category::getId).collect(Collectors.toList());
        // 3，根据分类ID，取对应关系的数据，并且这个删除标志为未删除，因为如果文章删除的话，对应关系也会同步删除。
        LambdaQueryWrapper<ArticleCategory> queryArticleCategoryWrapper = new LambdaQueryWrapper<>();
        queryArticleCategoryWrapper.in(ArticleCategory::getCategoryId,CategoryIds);
        List<ArticleCategory> articleCategories = articleCategoryMapper.selectList(queryArticleCategoryWrapper);

        //利用Map去存分类与文章的对应关系，这样在遍历取结果时，速度更快。并且两次的sql都是只单独执行。https://www.cnblogs.com/flydean/p/java-8-map-stream.html
        //这样做纯傻逼。可以使用list集合流直接做。
//        Map<Long,Long> hashMap = new HashMap<>();
//        for (ArticleCategory articleCategory: articleCategories) {
//            hashMap.put(articleCategory.getCategoryId(),articleCategory.getArticleId());
//            log.info("分类与文章对应关系表数据：分类【{}】，文章【{}】",articleCategory.getCategoryId(),articleCategory.getArticleId());
//        }

        List<CategorVo> categorVos = new ArrayList<>();
        for (Category category: categories) {
            CategorVo categorVo = new CategorVo();
            // 取出该分类id所对应的所有文章id，并转化成list集合。
            // Map的Stream遍历，可以好好整里整理。并且也要掌握 所有集合的底层，不然都不会。我现在就不太掌握

            //为啥只会显示一个2呢，是因为hashmap的键唯一，所以是替换了
//            List<Long> articleId = hashMap.entrySet().stream().filter(e -> category.getId().equals(e.getKey()))
//                    .map(Map.Entry::getValue)
//                    .collect(Collectors.toList());

            List<Long> articleIds = articleCategories.stream().filter(e -> category.getId().equals(e.getCategoryId()))
                    .map(ArticleCategory::getArticleId)
                    .collect(Collectors.toList());

            log.info("articleIds数据：{}",articleIds);
            //往分类的Vo对象存数据。
            categorVo.setArticleIds(articleIds);
            categorVo.setId(category.getId());
            categorVo.setName(category.getName());
            categorVo.setPid(category.getPid());
            log.info("categorVo数据：{}",categorVo);
            categorVos.add(categorVo);
        }

        return Result.success(categorVos);
    }
}
